#ifndef		__ENGINE_LOGGER_H_INCLUDED__
#define		__ENGINE_LOGGER_H_INCLUDED__

#include	<cstdio>
#include	<mutex>
#include	<string>

#define		LOG_INIT(name, ...)	Logger::Instance().Initialize(name, ##__VA_ARGS__)

#define		LOG_DEBUG(fmt, ...)	Logger::Instance().Write(Logger::Debug, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define		LOG_INFO(fmt, ...)	Logger::Instance().Write(Logger::Info, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define		LOG_WARN(fmt, ...)	Logger::Instance().Write(Logger::Warnning, __FILE__, __LINE__, fmt, ##__VA_ARGS__)
#define		LOG_ERR(fmt, ...)	Logger::Instance().Write(Logger::Error, __FILE__, __LINE__, fmt, ##__VA_ARGS__)

#define		LOG_ASSERT(expr, fmt, ...)			if (!(expr)) {\
	Logger::Instance().Write(Logger::Error, __FILE__, __LINE__, fmt, ##__VA_ARGS__);\
	return;\
}

#define		LOG_ASSERTR(expr, ret, fmt, ...)	if (!(expr)) {\
	Logger::Instance().Write(Logger::Error, __FILE__, __LINE__, fmt, ##__VA_ARGS__);\
	return expr;\
}

/**
 * File base log tool.
 *
 * 
 */
class Logger {
public:
	/** Log level filter. */
	enum Level {
		Error = 0,
		Warnning,
		Info,
		Debug
	};

public:
	Logger();
	~Logger();

	/**
	 * Get runtime singleton instance of log tool.
	 */
	static Logger & Instance();

	/**
	 * Initialize log settings. Optional but recommonded.
	 *
	 * \param name Log file prefix.
	 * \param root Directory that contains this log file.
	 * \param max_level Allowed max level of output message.
	 * \param capacity Max log file size. If current log file is larger than that a new file will be created.
	 */
	void Initialize(
		const std::string & name = "main",
		const std::string & root = "./logs",
		Level max_level = Level::Info,
		size_t capacity = 4 * 1024 * 1024);

	/**
	 * Write message into this log file.
	 *
	 * \param level Message level.
	 * \param file __FILE__
	 * \param line __LINE__
	 * \param fmt Output message fmt.
	 * \param ... Arguments to format this message.
	 */
	void Write(
		Level level,
		const char * file,
		int line,
		const char * fmt,
		...);

private:
	FILE * _file;
	char * _buf;
	std::string _name;
	std::string _path;
	size_t _capacity;
	size_t _writed;
	Level _allowed_max_level;
	int _last_day;
	std::mutex _lock;
};

#endif//!	__ENGINE_LOGGER_H_INCLUDED__
